package com.zues.thread.aqs;

import com.zues.thread.util.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * CountDownLatch学习测试
 *
 * @author zues
 * @date 4/1/2025 10:11 下午
 */
@Slf4j(topic = "c.CountDownLatchDemo1")
public class CountDownLatchDemo1 {

    public static void main(String[] args) throws Exception {

//        testResourceCheck();

//        testRaceStart();

        testMultiStage();
    }


    /**
     * 模拟3个任务，每个任务执行时间随机
     *
     * @return void
     * @throws InterruptedException
     * @author zues
     * @date 4/1/2025 10:11 下午
     */
    public void test1() throws InterruptedException {
// 初始化计数器（3个需要完成的任务）
        CountDownLatch countDownLatch = new CountDownLatch(3);

        // 使用线程池管理（可选优化）
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 3; i++) {
            final int taskId = i;
            executor.execute(() -> {
                try {
                    log.debug("任务{} 开始执行", taskId);
                    // 模拟任务执行时间
                    //1-3的随机整数

                    int random = new Random().nextInt(3) + 1;
                    ThreadUtil.sleep(random);
                    log.debug("任务{} 执行完成", taskId);
                } finally {
                    // 无论是否异常都减少计数
                    countDownLatch.countDown();
                    log.debug("计数器递减 [剩余：{}]", countDownLatch.getCount());
                }
            });
        }

        log.debug("主线程等待所有任务完成...");
        // 阻塞直到计数器归零
        countDownLatch.await();
        log.debug("所有任务已完成，继续主线程流程");

        // 关闭线程池（实际生产环境需要更优雅的关闭方式）
        executor.shutdown();
    }

    /**
     * 模拟资源初始化，等待所有资源就绪后开始提供服务
     *
     * @author zues
     */
    private static void testResourceCheck() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        ExecutorService executor = Executors.newFixedThreadPool(3);

        executor.execute(() -> {
            try {
                log.debug("正在初始化数据库连接...");
                ThreadUtil.sleep(new Random().nextInt(2) + 1);
                log.debug("数据库连接就绪");
            } finally {
                latch.countDown();
            }
        });

        executor.execute(() -> {
            try {
                log.debug("正在加载缓存数据...");
                ThreadUtil.sleep(new Random().nextInt(2) + 1);
                log.debug("缓存加载完成");
            } finally {
                latch.countDown();
            }
        });

        executor.execute(() -> {
            try {
                log.debug("正在读取配置文件...");
                ThreadUtil.sleep(new Random().nextInt(2) + 1);
                log.debug("配置加载完成");
            } finally {
                latch.countDown();
            }
        });

        log.debug("等待资源初始化。。。");
        latch.await();
        log.debug("所有资源已经就绪，开始提供服务");
        executor.shutdown();

    }


    /**
     * 场景二：赛跑比赛（所有选手就绪后同时开始）
     */
    private static void testRaceStart() throws InterruptedException {
        final int runnerCount = 5;
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch finishLatch = new CountDownLatch(runnerCount);

        for (int i = 1; i <= runnerCount; i++) {
            final int num = i;
            new Thread(() -> {
                try {
                    log.debug("选手{} 已就位", num);
                    startLatch.await(); // 等待发令枪响
                    log.debug("选手{} 开始奔跑", num);
                    ThreadUtil.sleep(new Random().nextInt(3) + 1);
                    log.debug("选手{} 到达终点", num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    finishLatch.countDown();
                }
            }).start();
        }

        log.debug("裁判准备发令...");
        ThreadUtil.sleep(2); // 模拟准备时间
        log.debug("比赛开始！");
        startLatch.countDown(); // 发令枪响
        finishLatch.await();
        log.debug("所有选手完成比赛");
    }


    /**
     * 场景三：分阶段任务处理（等待前序阶段完成）
     */
    private static void testMultiStage() throws InterruptedException {
        // 第一阶段：数据加载
        CountDownLatch loadLatch = new CountDownLatch(2);
        ExecutorService loader = Executors.newFixedThreadPool(2);

        loader.execute(() -> {
            log.debug("正在加载用户数据...");
            ThreadUtil.sleep(2);
            loadLatch.countDown();
        });

        loader.execute(() -> {
            log.debug("正在加载商品数据...");
            ThreadUtil.sleep(3);
            loadLatch.countDown();
        });

        loadLatch.await();
        log.debug("====== 所有数据加载完成 ======");

        // 第二阶段：处理数据
        CountDownLatch processLatch = new CountDownLatch(3);
        ExecutorService processor = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 3; i++) {
            final int batch = i;
            processor.execute(() -> {
                log.debug("正在处理批次{}数据...", batch);
                ThreadUtil.sleep(1);
                processLatch.countDown();
            });
        }

        processLatch.await();
        log.debug("====== 所有数据处理完成 ======");
        processor.shutdown();
        loader.shutdown();
    }
}
